package tp.pr5.instructions;

import tp.pr5.NavigationModule;
import tp.pr5.Place;
import tp.pr5.RobotEngine;
import tp.pr5.Street;
import tp.pr5.instructions.exceptions.InstructionExecutionException;
import tp.pr5.instructions.exceptions.WrongInstructionFormatException;
import tp.pr5.items.ItemContainer;

public class MoveInstruction extends UndoAble{
	RobotEngine rbt;
	NavigationModule nvm;

	/*
	 * Undo parameters
	 */

	
	
	@Override
	public Instruction parse(String cad) throws WrongInstructionFormatException {
		if(cad.equalsIgnoreCase("MOVE") || cad.equalsIgnoreCase("MOVER")){//si la acciÃ³n introducida es MOVE
			return new MoveInstruction();
		}else{
			throw new WrongInstructionFormatException();
			//throw new WrongInstructionFormatException();
		}
	}

	@Override
	public String getHelp() {
		return "     MOVE|MOVER";
	}

	@Override
	public void configureContext(RobotEngine engine,
			NavigationModule navigation, ItemContainer robotContainer) {
		this.rbt = engine;
		this.nvm = navigation;
		
	}

	@Override
	public void execute() throws InstructionExecutionException {
		Street calle = this.nvm.getaCity().lookForStreet(this.nvm.getCurrentPlace(), this.nvm.getCurrentHeading());
		
		if(calle != null){			
			if (!calle.isOpen()){				
				throw new InstructionExecutionException("WALL·E says: Arrggg, there is a street but it is closed!");
			}else{	//si la calle estÃ¡ abierta		
				this.nvm.move();							
				this.rbt.setFuel(this.rbt.getFuel() -5);				
			}
		}else{ 			
			throw new InstructionExecutionException("There is no street in direction "+this.nvm.getCurrentHeading().name());
		}
		
	}
	@Override
	public boolean isUndoAble() {

		return true;
	}
	/**
	 * revets the las instruction
	 * @throws InstructionExecutionException 
	 */
	public void undo() throws InstructionExecutionException {
		Street calle = this.nvm.getaCity().lookForStreet(this.nvm.getCurrentPlace(), this.nvm.getCurrentHeading().getOpposite());
		/*
		 * Refresh the interface
		 */
		Place lastPlace = this.nvm.getCurrentPlace();
		this.rbt.emitUnVisitPlace(lastPlace);
		
		if(calle != null){			
			this.nvm.setDirection(this.nvm.getCurrentHeading().getOpposite());
			
			Street nxtst = this.nvm.getaCity().lookForStreet(this.nvm.getCurrentPlace(), this.nvm.getCurrentHeading());
			if(nxtst != null){
				if(!nxtst.isOpen()){
					throw new InstructionExecutionException();
				}
				Place nxtplc = nxtst.nextPlace(this.nvm.getCurrentPlace());
				if(nxtplc != null){
					this.nvm.setCurrentPlace(nxtplc);//cambia el lugar actual por el siguiente
				}else{
					throw new InstructionExecutionException();
				}
			}else{
				throw new InstructionExecutionException();
			}
			
			this.nvm.setDirection(this.nvm.getCurrentHeading().getOpposite());
			this.rbt.setFuel(this.rbt.getFuel() +5);
			this.rbt.emitRobotUpdate();
			this.rbt.emitArrivedAtPlace();
					
			
		}else{ 			
			throw new InstructionExecutionException("There is no street in direction "+this.nvm.getCurrentHeading().name());
		}
	}

}
